/*
 * Copyright 2008-2010 Daniel Cachapa <cachapa@gmail.com>
 * 
 * This program is distributed under the terms of the GNU General Public License Version 3
 * The license can be read in its entirety in the LICENSE.txt file accompanying this source code,
 * or at: http://www.gnu.org/copyleft/gpl.html
 * 
 * This file is part of Libra.
 *
 * WeightWatch is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 *
 * WeightWatch is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with the WeightWatch source code. If not, see: http://www.gnu.org/licenses
 */

package net.cachapa.libra.component;

import java.util.List;

import net.cachapa.libra.R;
import net.cachapa.libra.adapter.ValueSelectorAdapter;
import net.cachapa.libra.util.UnitManager;
import net.cachapa.libra.util.Util;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.speech.RecognizerIntent;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Gallery;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.AdapterView.OnItemSelectedListener;

public class ValueSelector extends LinearLayout implements OnItemSelectedListener, OnFocusChangeListener, OnClickListener {
	public static final int TYPE_WEIGHT = 0;
	public static final int TYPE_HEIGHT = 1;
	public static final int VOICE_RECOGNITION_REQUEST_CODE = 25041974;
	
	private Activity activityCallback = null;
	private float currentValue;
	private int valueType;
	private OnValueChangedListener listener = null;
	
	public ValueSelector(Context context, AttributeSet attrs) {
		super(context, attrs);
	}
	
	public void setActivityCallback(Activity activityCallback) {
		this.activityCallback = activityCallback;
		// Check to see if a recognition activity is present
		PackageManager pm = getContext().getPackageManager();
		List<ResolveInfo> activities = pm.queryIntentActivities(
				new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0);
		if (activities.size() != 0) {
			ImageButton speakButton = (ImageButton) findViewById(R.id.SpeakButton);
			speakButton.setOnClickListener(this);
			speakButton.setVisibility(VISIBLE);
		}
	}
	
	@Override
	protected void onFinishInflate() {
		super.onFinishInflate();
		((Activity)getContext()).getLayoutInflater().inflate(R.layout.valueselector, this);
		
		Button valueButton = (Button) findViewById(R.id.ValueButton);
		valueButton.setOnClickListener(this);
		
		Gallery gallery = (Gallery) findViewById(R.id.ValuesGallery);
		gallery.setOnItemSelectedListener(this);
		gallery.setOnFocusChangeListener(this);
		
		this.clearFocus();
	}
	
	public float getValue() {
		return currentValue;
	}
	
	public void setValue(float value) {
		Gallery gallery = (Gallery) findViewById(R.id.ValuesGallery);
		ValueSelectorAdapter adapter = (ValueSelectorAdapter) gallery.getAdapter();
		gallery.setSelection(adapter.getPosition(value), true);	// No point in setting it to true -- it doesn't work
		// I'll still leave it, because I'm hopeful that it will work in some future version of Android
	}
	
	public void initialize(int min, int max, int decimalPlaces, int valueType) {
		int type = ValueSelectorAdapter.TYPE_GENERIC;
		if (valueType == TYPE_HEIGHT && !UnitManager.getInstance(getContext()).isMetricHeight()) {
			type = ValueSelectorAdapter.TYPE_HEIGHT_IMPERIAL;
		}
		else if (valueType == TYPE_WEIGHT && UnitManager.getInstance(getContext()).isStones()) {
			type = ValueSelectorAdapter.TYPE_WEIGHT_STONES;
		}
		this.valueType = valueType;
		Gallery gallery = (Gallery) findViewById(R.id.ValuesGallery);
		ValueSelectorAdapter adapter = new ValueSelectorAdapter(getContext(), min, max, decimalPlaces, type);
		gallery.setAdapter(adapter);
	}
	
	public void setOnValueChangedListener(OnValueChangedListener listener) {
		this.listener = listener;
	}
	
	public void onItemSelected(AdapterView<?> parent, View v, int position, long id) {
		Gallery gallery = (Gallery) findViewById(R.id.ValuesGallery);
		currentValue = ((ValueSelectorAdapter)gallery.getAdapter()).getValue(id);
		
		updateValue();
		
		if (listener != null) {
			listener.valueChanged(currentValue);
		}
	}
	
	private void updateValue() {
		Button valueButton = (Button) findViewById(R.id.ValueButton);
		UnitManager um = UnitManager.getInstance(getContext());
		switch (valueType) {
		case TYPE_WEIGHT:
			valueButton.setText(um.toWeightUnit(currentValue));
			break;
		case TYPE_HEIGHT:
			valueButton.setText(um.toHeightUnit(currentValue));
			break;
		};
	}

	public void onNothingSelected(AdapterView<?> parent) {
		// Not needed (me thinks)
	}
	
	public void onFocusChange(View v, boolean hasFocus) {
		if (v.getId() == R.id.ValuesGallery) {
			if (hasFocus) {
				v.setBackgroundResource(R.drawable.highlight_selected);
			}
			else {
				v.setBackgroundResource(R.drawable.highlight_disabled);
			}
		}
	}
	
	public void onClick(View v) {
		if (v.getId() == R.id.ValueButton) {
			boolean imperialHeight = valueType == TYPE_HEIGHT && !UnitManager.getInstance(getContext()).isMetricHeight();
			boolean stones = valueType == TYPE_WEIGHT && UnitManager.getInstance(getContext()).isStones();
			if (imperialHeight) {
				showValueDialogHeight();
			}
			else if (stones) {
				showValueDialogStones();
			}
			else {
				showValueDialog();
			}
		}
		
		if (v.getId() == R.id.SpeakButton) {
			Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
			intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
					RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
			intent.putExtra(RecognizerIntent.EXTRA_PROMPT, getContext().getString(R.string.speak_value));
			activityCallback.startActivityForResult(intent, VOICE_RECOGNITION_REQUEST_CODE);
		}
	}
	
	private AlertDialog showValueDialog() {
		UnitManager um = UnitManager.getInstance(getContext());
		
		final View valueLayout = LayoutInflater.from(getContext()).inflate(R.layout.valuedialog, null);
		TextView unitTextView = (TextView) valueLayout.findViewById(R.id.UnitTextView);
		final EditText valueEditText = (EditText) valueLayout.findViewById(R.id.ValueEditText);
		valueEditText.setText(currentValue + "");
		
		switch (valueType) {
		case TYPE_WEIGHT:
			unitTextView.setText(um.getWeightUnit());
			break;
		case TYPE_HEIGHT:
			unitTextView.setText(um.getHeightUnit());
			break;
		};
				
		return new AlertDialog.Builder(getContext())
			.setView(valueLayout)
			.setPositiveButton(android.R.string.ok,new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog, int whichButton) {
					try {
						float newValue = Float.valueOf(valueEditText.getText().toString());
						setValue(newValue);
					} catch (Exception e) {
						// Ignore it
					}
				}
			})
			.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog,	int whichButton) {
					// Do nothing
				}
			}).show();
	}
	
	private AlertDialog showValueDialogHeight() {
		final UnitManager um = UnitManager.getInstance(getContext());
		
		final View valueLayout = LayoutInflater.from(getContext()).inflate(R.layout.valuedialog_height, null);
		final EditText feetEditText = (EditText) valueLayout.findViewById(R.id.FeetEditText);
		final EditText inchesEditText = (EditText) valueLayout.findViewById(R.id.InchesEditText);
		
		int[] values = um.inchesToFeetInches((int) currentValue);
		feetEditText.setText(values[0] + "");
		inchesEditText.setText(values[1] + "");
		
		return new AlertDialog.Builder(getContext())
			.setView(valueLayout)
			.setPositiveButton(android.R.string.ok,new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog, int whichButton) {
					
					try {
						int feet = Integer.valueOf(feetEditText.getText().toString());
						int inches = Integer.valueOf(inchesEditText.getText().toString());
						setValue(um.feetInchesToInches(feet, inches));
					} catch (Exception e) {
						// Ignore it
					}
				}
			})
			.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog,	int whichButton) {
					// Do nothing
				}
			}).show();
	}
	
	private AlertDialog showValueDialogStones() {
		final View valueLayout = LayoutInflater.from(getContext()).inflate(R.layout.valuedialog_stones, null);
		final EditText stonesEditText = (EditText) valueLayout.findViewById(R.id.StonesEditText);
		final EditText poundsEditText = (EditText) valueLayout.findViewById(R.id.PoundsEditText);
		
		stonesEditText.setText((int) (currentValue / 14) + "");
		poundsEditText.setText(Util.Round(currentValue %14, 1) + "");
		
		return new AlertDialog.Builder(getContext())
			.setView(valueLayout)
			.setPositiveButton(android.R.string.ok,new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog, int whichButton) {
					
					try {
						int stones = Integer.valueOf(stonesEditText.getText().toString());
						float pounds = Float.valueOf(poundsEditText.getText().toString());
						setValue(stones * 14 + pounds);
					} catch (Exception e) {
						// Ignore it
					}
				}
			})
			.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog,	int whichButton) {
					// Do nothing
				}
			}).show();
	}
	
	
	
	public interface OnValueChangedListener {
		public void valueChanged(float newValue);
	}
}